emit finished();
}
-FakePutMultiFileReply::FakePutMultiFileReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, const QString &contentType, const QByteArray &putPayload, QObject *parent)
+FakePutMultiFileReply::FakePutMultiFileReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, const QString &contentType, const QByteArray &putPayload, const QString &serverVersion, QObject *parent)
: FakeReply { parent }
+ , _serverVersion(serverVersion)
{
setRequest(request);
setUrl(request.url());
setOperation(op);
open(QIODevice::ReadOnly);
- _allFileInfo = performMultiPart(remoteRootFileInfo, request, putPayload, contentType);
+ _allFileInfo = performMultiPart(remoteRootFileInfo, request, putPayload, contentType, _serverVersion);
QMetaObject::invokeMethod(this, "respond", Qt::QueuedConnection);
}
-QVector<FileInfo *> FakePutMultiFileReply::performMultiPart(FileInfo &remoteRootFileInfo, const QNetworkRequest &request, const QByteArray &putPayload, const QString &contentType)
+QVector<FileInfo *> FakePutMultiFileReply::performMultiPart(FileInfo &remoteRootFileInfo, const QNetworkRequest &request, const QByteArray &putPayload, const QString &contentType, const QString &serverVersion)
{
Q_UNUSED(request)
QVector<FileInfo *> result;
const auto standardChecksum = allHeaders[QStringLiteral("oc-checksum")];
Q_ASSERT(!fileName.isEmpty());
Q_ASSERT(modtime > 0);
- Q_ASSERT(!expectedMd5Checksum.isEmpty());
+
+ auto components = serverVersion.split('.');
+ const auto serverIntVersion = OCC::Account::makeServerVersion(components.value(0).toInt(),
+ components.value(1).toInt(),
+ components.value(2).toInt());
+
+ const auto md5ChecksumMandatory = serverIntVersion < OCC::Account::makeServerVersion(32, 0, 0);
+
+ if (md5ChecksumMandatory) {
+ Q_ASSERT(!expectedMd5Checksum.isEmpty());
+ } else {
+ Q_ASSERT(expectedMd5Checksum.isEmpty());
+ }
Q_ASSERT(!standardChecksum.isEmpty());
const auto standardChecksumComponents = standardChecksum.split(':');
Q_ASSERT(false);
}
- QCryptographicHash md5SumAlgorithm{QCryptographicHash::Algorithm::Md5};
- QCryptographicHash standardSumAlgorithm{standardHashAlgorithm};
+ if (md5ChecksumMandatory) {
+ QCryptographicHash md5SumAlgorithm{QCryptographicHash::Algorithm::Md5};
+
+ md5SumAlgorithm.addData(onePartBody.toLatin1());
+ const auto computedMd5Checksum = md5SumAlgorithm.result().toHex();
+ Q_ASSERT(expectedMd5Checksum == computedMd5Checksum);
+ }
- md5SumAlgorithm.addData(onePartBody.toLatin1());
- const auto computedMd5Checksum = md5SumAlgorithm.result().toHex();
- Q_ASSERT(expectedMd5Checksum == computedMd5Checksum);
+ QCryptographicHash standardSumAlgorithm{standardHashAlgorithm};
standardSumAlgorithm.addData(onePartBody.toLatin1());
const auto computedStandardChecksum = standardSumAlgorithm.result().toHex();
reply = new FakeChunkMoveReply { info, _remoteRootFileInfo, op, newRequest, this };
} else if (verb == QLatin1String("POST") || op == QNetworkAccessManager::PostOperation) {
if (contentType.startsWith(QStringLiteral("multipart/related; boundary="))) {
- reply = new FakePutMultiFileReply { info, op, newRequest, contentType, outgoingData->readAll(), this };
+ reply = new FakePutMultiFileReply { info, op, newRequest, contentType, outgoingData->readAll(), _serverVersion, this };
}
} else if (verb == QLatin1String("LOCK") || verb == QLatin1String("UNLOCK")) {
reply = new FakeFileLockReply{info, op, newRequest, this};
return reply;
}
+void FakeQNAM::setServerVersion(const QString &version)
+{
+ _serverVersion = version;
+}
+
FakeFolder::FakeFolder(const FileInfo &fileTemplate, const OCC::Optional<FileInfo> &localFileInfo, const QString &remotePath)
: _localModifier(_tempDir.path())
{
_account->setUrl(QUrl(QStringLiteral("http://admin:admin@localhost/owncloud")));
_account->setCredentials(new FakeCredentials { _fakeQnam });
_account->setDavDisplayName(QStringLiteral("fakename"));
- _account->setServerVersion(QStringLiteral("10.0.0"));
+ _account->setServerVersion(_serverVersion);
+ _fakeQnam->setServerVersion(_serverVersion);
_journalDb = std::make_unique<OCC::SyncJournalDb>(localPath() + QStringLiteral(".sync_test.db"));
_syncEngine = std::make_unique<OCC::SyncEngine>(_account, localPath(), OCC::SyncOptions{}, remotePath, _journalDb.get());
});
}
+void FakeFolder::setServerVersion(const QString &version)
+{
+ if (_serverVersion == version) {
+ return;
+ }
+
+ _serverVersion = version;
+ _account->setServerVersion(_serverVersion);
+ _fakeQnam->setServerVersion(_serverVersion);
+}
+
FileInfo FakeFolder::currentLocalState()
{
QDir rootDir { _tempDir.path() };
{
Q_OBJECT
public:
- FakePutMultiFileReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, const QString &contentType, const QByteArray &putPayload, QObject *parent);
+ FakePutMultiFileReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, const QString &contentType, const QByteArray &putPayload, const QString &serverVersion, QObject *parent);
- static QVector<FileInfo *> performMultiPart(FileInfo &remoteRootFileInfo, const QNetworkRequest &request, const QByteArray &putPayload, const QString &contentType);
+ static QVector<FileInfo *> performMultiPart(FileInfo &remoteRootFileInfo, const QNetworkRequest &request, const QByteArray &putPayload, const QString &contentType, const QString &serverVersion);
Q_INVOKABLE virtual void respond();
QVector<FileInfo *> _allFileInfo;
QByteArray _payload;
+
+ QString _serverVersion;
};
class FakeMkcolReply : public FakeReply
// monitor requests and optionally provide custom replies
Override _override;
+ QString _serverVersion = QStringLiteral("10.0.0");
+
public:
FakeQNAM(FileInfo initialRoot);
FileInfo ¤tRemoteState() { return _remoteRootFileInfo; }
QNetworkReply *overrideReplyWithError(QString fileName, Operation op, QNetworkRequest newRequest);
+ void setServerVersion(const QString &version);
+
protected:
QNetworkReply *createRequest(Operation op, const QNetworkRequest &request,
QIODevice *outgoingData = nullptr) override;
OCC::AccountPtr _account;
std::unique_ptr<OCC::SyncJournalDb> _journalDb;
std::unique_ptr<OCC::SyncEngine> _syncEngine;
+ QString _serverVersion = QStringLiteral("10.0.0");
public:
FakeFolder(const FileInfo &fileTemplate, const OCC::Optional<FileInfo> &localFileInfo = {}, const QString &remotePath = {});
void enableEnforceWindowsFileNameCompatibility();
+ void setServerVersion(const QString &version);
+
[[nodiscard]] OCC::AccountPtr account() const { return _account; }
[[nodiscard]] OCC::SyncEngine &syncEngine() const { return *_syncEngine; }
[[nodiscard]] OCC::SyncJournalDb &syncJournal() const { return *_journalDb; }
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
}
+ void testDirUploadWithDelayedAlgorithmWithNewChecksum() {
+ FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
+ fakeFolder.setServerVersion(QStringLiteral("32.0.0"));
+ fakeFolder.syncEngine().account()->setCapabilities({ { "dav", QVariantMap{ {"bulkupload", "1.0"} } } });
+
+ ItemCompletedSpy completeSpy(fakeFolder);
+ fakeFolder.localModifier().mkdir("Y");
+ fakeFolder.localModifier().insert("Y/d0");
+ fakeFolder.localModifier().mkdir("Z");
+ fakeFolder.localModifier().insert("Z/d0");
+ fakeFolder.localModifier().insert("A/a0");
+ fakeFolder.localModifier().insert("B/b0");
+ fakeFolder.localModifier().insert("r0");
+ fakeFolder.localModifier().insert("r1");
+ fakeFolder.syncOnce();
+ QVERIFY(itemDidCompleteSuccessfullyWithExpectedRank(completeSpy, "Y", 0));
+ QVERIFY(itemDidCompleteSuccessfullyWithExpectedRank(completeSpy, "Z", 1));
+ QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Y/d0"));
+ QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "Y/d0") > 1);
+ QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Z/d0"));
+ QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "Z/d0") > 1);
+ QVERIFY(itemDidCompleteSuccessfully(completeSpy, "A/a0"));
+ QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "A/a0") > 1);
+ QVERIFY(itemDidCompleteSuccessfully(completeSpy, "B/b0"));
+ QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "B/b0") > 1);
+ QVERIFY(itemDidCompleteSuccessfully(completeSpy, "r0"));
+ QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "r0") > 1);
+ QVERIFY(itemDidCompleteSuccessfully(completeSpy, "r1"));
+ QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "r1") > 1);
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+ }
+
void testLocalDelete() {
FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
ItemCompletedSpy completeSpy(fakeFolder);